package cn.rayland.library.utils;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;

public class IOUtils {
	
	  private static final int BUFFER_SIZE = 1024 * 8;

	public static void readUrl(final URL url, final Handler handler) {
		  new Thread(new Runnable() {
			public void run() {
				  Message msg = new Message();  
			      Bundle data = new Bundle(); 
				  try {
					  StringBuilder result = new StringBuilder();
					  BufferedReader in = new BufferedReader(
						   new InputStreamReader(url.openStream(), "UTF-8"));
					  String line = null;
					  while ((line = in.readLine()) != null)
						  result.append(line + "\n");
					   data.putString("response", result.toString());
					   msg.setData(data);
					   handler.sendMessage(msg);
				  } catch (IOException e) {
					  e.printStackTrace();
				  }
			  }
		  }).start();  
	}
	
	public static class ReadUrl implements Runnable {
		public String mResult;
		private URL mUrl;
		private Handler mHandler;
		private Runnable mCallback;
		public ReadUrl(URL url) {
			mUrl = url;
			mHandler = new Handler();
		}
		public String toString() {
			return mResult;
		}
		public ReadUrl onFinish(Runnable callback) {
			mCallback = callback;
			return this;
		}
		public void startThread() {
			new Thread(this).start();
		}
		public void run() {
		  try {
			  StringBuilder result = new StringBuilder();
			  BufferedReader in = new BufferedReader(
				   new InputStreamReader(mUrl.openStream(), "UTF-8"));
			  String line = null;
			  while ((line = in.readLine()) != null)
				  result.append(line + "\n");
			  mResult = result.toString();
			  mHandler.post(mCallback);
		  } catch (IOException e) {
			  e.printStackTrace();
		  }
	  }
	}
	
	public static byte[] readToBytes(InputStream input) throws IOException {
		ByteArrayOutputStream output = new ByteArrayOutputStream(4096);
		byte[] buffer = new byte[1024 * 4];
		int n = 0;
		while (-1 != (n = input.read(buffer))) {
			output.write(buffer, 0, n);
		}
		return output.toByteArray();
	}
	
	public static String bytesToString(byte[] bytes) throws IOException {
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		out.write(bytes);
		return out.toString();
	}
	
	public static String readToString(InputStream input) throws IOException {
		return bytesToString(readToBytes(input));
	}
	
	public static int copyAndClose(InputStream input, OutputStream output) throws Exception, IOException {
	    byte[] buffer = new byte[BUFFER_SIZE];

	    BufferedInputStream in = new BufferedInputStream(input, BUFFER_SIZE);
	    BufferedOutputStream out = new BufferedOutputStream(output, BUFFER_SIZE);
	    int count = 0, n = 0;
	    try {
	      while ((n = in.read(buffer, 0, BUFFER_SIZE)) != -1) {
	        out.write(buffer, 0, n);
	        count += n;
	      }
	      out.flush();
	    } finally {
	      try {
	        out.close();
	      } catch (IOException e) {
	        Log.e(e.getMessage(), e.toString());
	      }
	      try {
	        in.close();
	      } catch (IOException e) {
	        Log.e(e.getMessage(), e.toString());
	      }
	    }
	    return count;
	  }
	
	/**
	 * Convert <code>input</code> stream into byte[].
	 * 
	 * @param input
	 * @return Array of Byte
	 * @throws IOException
	 */
	public static byte[] toByteArray(InputStream input) throws IOException {
		ByteArrayOutputStream output = new ByteArrayOutputStream();
		copy(input, output);
		return output.toByteArray();
	}
	
	/**
	 * Copy <code>length</code> size of <code>input</code> stream to <code>output</code> stream.
	 * This method will NOT close input and output stream.
	 * 
	 * @param input
	 * @param output
	 * @return long copied length
	 * @throws IOException
	 */
	public static long copy(InputStream input, OutputStream output) throws IOException {
		byte[] buffer = new byte[BUFFER_SIZE];
		long count = 0;
		int n = 0;
		while ((n = input.read(buffer)) != -1) {
			output.write(buffer, 0, n);
			count += n;
		}
		return count;
	}

	/**
	 * Copy <code>length</code> size of <code>input</code> stream to <code>output</code> stream.
	 * 
	 * @param input
	 * @param output
	 * @return long copied length
	 * @throws IOException
	 */
	public static long copy(InputStream input, OutputStream output, int length) throws IOException {
		byte[] buffer = new byte[length];
		int count = 0;
		int n = 0;
		int max = length;
		while ((n = input.read(buffer, 0, max)) != -1) {
			output.write(buffer, 0, n);
			count += n;
			if (count > length) {
				break;
			}
			
			max -= n;
			if (max <= 0) {
				break;
			}
		}
		return count;
	}
	
	/**
	 * Close <code>closeable</code> quietly.
	 * 
	 * @param closeable
	 */
	public static void closeQuietly(Closeable closeable) {
		if (closeable == null) {
			return;
		}
		
		try {
			closeable.close();
		} catch (Throwable e) {
			// do nothing
		}		
	}

	public static byte[] toByteArray(String path) {
		byte[] bytes = null;
		try {
			bytes = IOUtils.toByteArray(new FileInputStream(path));
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return bytes;
	}

	/**
	 * 根据byte数组，生成文件
	 */
	public static void save2File(byte[] bfile, String filePath,String fileName) {
		BufferedOutputStream bos = null;
		FileOutputStream fos = null;
		File file = null;
		try {
			File dir = new File(filePath);
			if(!dir.exists()&&dir.isDirectory()){//判断文件目录是否存在
				dir.mkdirs();
			}
			file = new File(filePath+"/"+fileName);
			fos = new FileOutputStream(file);
			bos = new BufferedOutputStream(fos);
			bos.write(bfile);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (bos != null) {
				try {
					bos.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		}
	}
}
